home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / lib / include / sync.h < prev    next >
C/C++ Source or Header  |  1991-08-09  |  7KB  |  211 lines

  1. /*
  2.  * sync.h --
  3.  *
  4.  *     Typedefs and macros to support the use of monitors.
  5.  *      Clients use the macros to acquire and release monitor locks, and
  6.  *      to wait on and notify monitored condition variables.  Only Broadcast
  7.  *      semantics are supported for lock release; that is, all processes
  8.  *      waiting on a lock are made runnable when the locked is released.
  9.  *
  10.  *      These macros do a fast check on the state of the lock or condition
  11.  *      variable to reduce overhead.  In the best case the lock and unlock
  12.  *      routines just set or clear flags.  In the worst case these routines
  13.  *      have to call slower routines that must acquire a master lock.
  14.  *
  15.  * Copyright 1986, 1988 Regents of the University of California
  16.  * Permission to use, copy, modify, and distribute this
  17.  * software and its documentation for any purpose and without
  18.  * fee is hereby granted, provided that the above copyright
  19.  * notice appear in all copies.  The University of California
  20.  * makes no representations about the suitability of this
  21.  * software for any purpose.  It is provided "as is" without
  22.  * express or implied warranty.
  23.  *
  24.  *
  25.  * $Header: /sprite/src/lib/include/RCS/sync.h,v 1.7 90/01/16 17:59:49 jhh Exp $ SPRITE (Berkeley)
  26.  */
  27.  
  28. #ifndef _SYNCUSER
  29. #define _SYNCUSER
  30.  
  31. #ifndef _SPRITE
  32. #include "sprite.h"
  33. #endif
  34.  
  35. /*
  36.  * The state of a lock consists of two bits of information, a lock bit
  37.  * and a waiting bit.  The lock bit indicates that someone has the
  38.  * lock, and no other process can acquire the lock until this bit is
  39.  * cleared.  The waiting bit indicates that someone wants the lock.
  40.  *
  41.  * The user locks are different from the kernel locks. If we are compiling
  42.  * user code then the Sync_UserLock type is typedef'ed to be Sync_Lock.
  43.  * The Sync_UserLock type is used by the kernel to differentiate between
  44.  * the two types of locks.
  45.  *
  46.  * Note: the inUse field is a whole word so it can be
  47.  *       an argument to the test-and-set instruction.
  48.  */
  49.  
  50. typedef struct Sync_UserLock {
  51.     Boolean inUse;        /* 1 while the lock is busy */
  52.     Boolean waiting;        /* 1 if someone wants the lock */
  53. } Sync_UserLock;
  54.  
  55. #ifndef KERNEL 
  56. typedef Sync_UserLock Sync_Lock;     /* define user locks */
  57. #endif
  58.  
  59. /*
  60.  * Condition variables represent events that are associated with
  61.  * locks.  The operations on a condition variable are Sync_Wait and
  62.  * Sync_Broadcast. The lock must be acquired before a call to
  63.  * Sync_Wait is made.  The lock is released while a process waits on a
  64.  * condition, and is then re-acquired when the condition is notified
  65.  * via Sync_Broadcast.
  66.  */
  67.  
  68. typedef struct Sync_Condition {
  69.     Boolean waiting;        /* 1 if someone is waiting on the condition */
  70. } Sync_Condition;
  71.  
  72. /*
  73.  * Maximum number of prior locks that can exist for any type of lock. A prior
  74.  * lock is the last lock to be grabbed by the process grabbing the current 
  75.  * lock. Keeping track of the locks held by a process is done in the proc
  76.  * module. By knowing all the prior locks of a lock it is possible to 
  77.  * construct a tree representing the locking behavior of the system.
  78.  * SYNC_MAX_PRIOR places a limit on how many prior locks will be remembered
  79.  * for an individual lock.
  80.  */
  81.  
  82. #ifndef LOCKDEP
  83. #define SYNC_MAX_PRIOR 1
  84. #else
  85. #define SYNC_MAX_PRIOR 30
  86. #endif
  87.  
  88. /*
  89.  * This structure is used to pass locking statistics to user programs.
  90.  * One of these structures is needed per lock type.
  91.  */
  92. typedef struct {
  93.     int        inUse;                /* 1 if structure is valid  */
  94.     int        class;                /* 0 = semaphore, 1 = lock */
  95.     int        hit;                /* # times lock was grabbed */
  96.     int        miss;                /* # times lock was missed */
  97.     char    name[30];            /* name of lock */
  98.     int        priorCount;            /* # of prior locks  */
  99.     int        priorTypes[SYNC_MAX_PRIOR];    /* types of prior locks */
  100.     int        activeCount;            /* # active locks of type */
  101.     int        deadCount;            /* # dead locks of type */
  102.     int        spinCount;            /* # spins waiting for lock */
  103. } Sync_LockStat;
  104.  
  105.  
  106. /*
  107.  * ----------------------------------------------------------------------------
  108.  *
  109.  * Monitor Locks --
  110.  *
  111.  *    The following set of macros are used to emulate monitored
  112.  *    procedures of Mesa.  The Sprite style document has a complete
  113.  *    description of the conventions required to emulate a set
  114.  *    of monitored procedures; a summary is presented here.
  115.  *
  116.  *      The LOCK_MONITOR and UNLOCK_MONITOR macros depend on a constant
  117.  *      LOCKPTR.  LOCKPTR should be defined as the address of the lock
  118.  *      variable used to lock the monitor.  Something like the following
  119.  *      two lines of code should appear at the beginning of a file of
  120.  *      monitored procedures.
  121.  *
  122.  *    Sync_Lock modMonitorLock;
  123.  *    #define LOCKPTR (&modMonitorLock)
  124.  *
  125.  *    The pseudo-keywords INTERNAL and ENTRY denote internal and entry
  126.  *    procedures of a monitor.  INTERNAL procedures can only be called
  127.  *    when the monitor lock is held.  ENTRY procedures are procedures
  128.  *    that acquire the lock.  There may also be External procedures.
  129.  *    They are the default and there is no special keyword.  An External
  130.  *    procedure doesn't explicitly acquire the monitor lock, but may
  131.  *    call an ENTRY procedure.
  132.  *
  133.  * ----------------------------------------------------------------------------
  134.  */
  135.  
  136. #define LOCK_MONITOR               (void) Sync_GetLock(LOCKPTR)
  137. #define UNLOCK_MONITOR             (void) Sync_Unlock(LOCKPTR)
  138.  
  139. #define ENTRY
  140. #define INTERNAL
  141.  
  142.  
  143. /*
  144.  * ----------------------------------------------------------------------------
  145.  *
  146.  * Sync_Wait --
  147.  *
  148.  * Wait on a condition variable.  This can only be called while a lock
  149.  * is aquired because it is only safe to check global state while in a
  150.  * monitor.  This releases the monitor lock and makes the process sleep
  151.  * on the condition. The monitor lock is reacquired after the process 
  152.  * has been woken up.
  153.  *
  154.  * The address of the condition variable is used as the generic 'event'
  155.  * that the process blocks on.  The value of the condition variable is
  156.  * used to indicate if there is a process waiting on the condition.
  157.  *
  158.  * Results:
  159.  *    None.
  160.  *
  161.  * Side effects:
  162.  *    Put the process to sleep and release the monitor lock.
  163.  *
  164.  * ----------------------------------------------------------------------------
  165.  */
  166.  
  167. #define Sync_Wait(conditionPtr, wakeIfSignal) \
  168.     Sync_SlowWait(conditionPtr, LOCKPTR, wakeIfSignal)
  169.  
  170.  
  171. /*
  172.  * ----------------------------------------------------------------------------
  173.  *
  174.  * Sync_Broadcast --
  175.  *
  176.  *      Notify other processes that a condition has been met.  If the
  177.  *      condition variable indicates that there are processes waiting
  178.  *      on the condition, then Sync_SlowBroadcast is used to wakeup
  179.  *      waiting processes.
  180.  *
  181.  * Monitor Lock:
  182.  *    This routine needs to be called with the monitor lock held.
  183.  *    This ensures synchronous access to the conditionPtr->waiting flag.
  184.  *
  185.  * Results:
  186.  *    None.
  187.  *
  188.  * Side effects:
  189.  *    Make the processes waiting on the condition variable runnable.
  190.  *
  191.  * ----------------------------------------------------------------------------
  192.  */
  193.  
  194. #define Sync_Broadcast(conditionPtr) \
  195.     if (((Sync_Condition *)conditionPtr)->waiting == TRUE)  { \
  196.     (void)Sync_SlowBroadcast((unsigned int) conditionPtr, \
  197.       &((Sync_Condition *)conditionPtr)->waiting); \
  198.     }
  199.  
  200. /*
  201.  * Exported procedures of the sync module for monitors.
  202.  */
  203.  
  204. extern ReturnStatus    Sync_GetLock();
  205. extern ReturnStatus    Sync_Unlock();
  206. extern ReturnStatus    Sync_SlowLock();
  207. extern ReturnStatus    Sync_SlowWait();
  208. extern ReturnStatus    Sync_SlowBroadcast();
  209.  
  210. #endif /* _SYNCUSER */
  211.